Trò chơi Pac-Man

20.578 lượt xem;
1 using System;
2 using
System.Collections.Generic;
3 using
System.IO;
4 using
UnityEngine;
5
6 public
class GhostMove : MonoBehaviour {
7
8     
// ----------------------------
9     
// Navigation variables
10     
private Vector3 waypoint; // AI-determined waypoint
11     
private Queue<Vector3> waypoints; // waypoints used on Init and Scatter states
12
13     
// direction is set from the AI component
14     
public Vector3 _direction;
15     
public Vector3 direction
16     {
17         
get
18         {
19             
return _direction;
20         }
21
22         
set
23         {
24             _direction =
value;
25             Vector3 pos =
new Vector3((int)transform.position.x, (int)transform.position.y, (int)transform.position.z);
26             waypoint = pos + _direction;
27             
//Debug.Log ("waypoint (" + waypoint.position.x + ", " + waypoint.position.y + ") set! _direction: " + _direction.x + ", " + _direction.y);
28         
29         }
30     }
31
32     
public float speed = 0.3f;
33
34     
// ----------------------------
35     
// Ghost mode variables
36     
public float scatterLength = 5f;
37     
public float waitLength = 0.0f;
38
39     
private float timeToEndScatter;
40     
private float timeToEndWait;
41
42     
enum State { Wait, Init, Scatter, Chase, Run };
43     State state;
44
45     
private Vector3 _startPos;
46     
private float _timeToWhite;
47     
private float _timeToToggleWhite;
48     
private float _toggleInterval;
49     
private bool isWhite = false;
50
51     
// handles
52     
public GameGUINavigation GUINav;
53     
public PlayerController pacman;
54     
private GameManager _gm;
55
56     
//-----------------------------------------------------------------------------------------
57     
// variables end, functions begin
58     
void Start()
59     {
60         _gm = GameObject.Find(
"Game Manager").GetComponent<GameManager>();
61         _toggleInterval = _gm.scareLength *
0.33f * 0.20f;
62         InitializeGhost();
63     }
64
65     
public float DISTANCE;
66
67     
void FixedUpdate ()
68     {
69         DISTANCE = Vector3.Distance(transform.position, waypoint);
70
71         
if(GameManager.gameState == GameManager.GameState.Game){
72             animate ();
73
74             
switch(state)
75             {
76             
case State.Wait:
77                 Wait();
78                 
break;
79
80             
case State.Init:
81                 Init();
82                 
break;
83
84             
case State.Scatter:
85                 Scatter();
86                 
break;
87
88             
case State.Chase:
89                 ChaseAI();
90                 
break;
91
92             
case State.Run:
93                 RunAway();
94                 
break;
95             }
96         }
97     }
98
99     
//-----------------------------------------------------------------------------------
100     
// Start() functions
101
102     
public void InitializeGhost()
103     {
104         _startPos = getStartPosAccordingToName();
105         waypoint = transform.position;
// to avoid flickering animation
106         state = State.Wait;
107         timeToEndWait = Time.time + waitLength + GUINav.initialDelay;
108         InitializeWaypoints(state);
109     }
110
111     
public void InitializeGhost(Vector3 pos)
112     {
113         transform.position = pos;
114         waypoint = transform.position;
// to avoid flickering animation
115         state = State.Wait;
116         timeToEndWait = Time.time + waitLength + GUINav.initialDelay;
117         InitializeWaypoints(state);
118     }
119     
120
121     
private void InitializeWaypoints(State st)
122     {
123         
//--------------------------------------------------
124         
// File Format: Init and Scatter coordinates separated by empty line
125         
// Init X,Y
126         
// Init X,Y
127         
//
128         
// Scatter X,Y
129         
// Scatter X,Y
130
131         
//--------------------------------------------------
132         
// hardcode waypoints according to name.
133         
string data = "";
134         
switch (name)
135         {
136         
case "blinky":
137             data =
@"22 20
138 22
26
139
140 27
26
141 27
30
142 22
30
143 22
26";
144             
break;
145         
case "pinky":
146             data =
@"14.5 17
147 14
17
148 14
20
149 7
20
150
151 7
26
152 7
30
153 2
30
154 2
26";
155             
break;
156         
case "inky":
157             data =
@"16.5 17
158 15
17
159 15
20
160 22
20
161
162 22
8
163 19
8
164 19
5
165 16
5
166 16
2
167 27
2
168 27
5
169 22
5";
170             
break;
171         
case "clyde":
172             data =
@"12.5 17
173 14
17
174 14
20
175 7
20
176
177 7
8
178 7
5
179 2
5
180 2
2
181 13
2
182 13
5
183 10
5
184 10
8";
185             
break;
186         
187         }
188
189         
//-------------------------------------------------
190         
// read from the hardcoded waypoints
191         
string line;
192
193         waypoints =
new Queue<Vector3>();
194         Vector3 wp;
195
196         
if (st == State.Init)
197         {
198             
using (StringReader reader = new StringReader(data))
199             {
200                 
// stop reading if empty line is reached
201                 
while ((line = reader.ReadLine()) != null)
202                 {
203                     
if (line.Length == 0) break; // DOES IT WORK????
204
205                     
string[] values = line.Split(' ');
206                     
float x = float.Parse(values[0]);
207                     
float y = float.Parse(values[1]);
208
209                     wp =
new Vector3(x, y, 0);
210                     waypoints.Enqueue(wp);
211                 }
212             }
213         }
214
215         
if (st == State.Scatter)
216         {
217             
// skip until empty line is reached, read coordinates afterwards
218             
bool scatterWps = false; // Scatter waypoints
219
220             
using (StringReader reader = new StringReader(data))
221             {
222                 
while ((line = reader.ReadLine()) != null)
223                 {
224                     
if (line.Length == 0)
225                     {
226                         scatterWps =
true; // we reached the scatter waypoints
227                         
continue; // do not read empty line, go to next line
228                     }
229
230                     
if (scatterWps)
231                     {
232                         
string[] values = line.Split(' ');
233                         
int x = Int32.Parse(values[0]);
234                         
int y = Int32.Parse(values[1]);
235
236                         wp =
new Vector3(x, y, 0);
237                         waypoints.Enqueue(wp);
238                     }
239                 }
240             }
241         }
242
243         
// if in wait state, patrol vertically
244         
if (st == State.Wait)
245         {
246             Vector3 pos = transform.position;
247
248             
// inky and clyde start going down and then up
249             
if (transform.name == "inky" || transform.name == "clyde")
250             {
251                 waypoints.Enqueue(
new Vector3(pos.x, pos.y - 0.5f, 0f));
252                 waypoints.Enqueue(
new Vector3(pos.x, pos.y + 0.5f, 0f));
253             }
254             
// while pinky start going up and then down
255             
else
256             {
257                 waypoints.Enqueue(
new Vector3(pos.x, pos.y + 0.5f, 0f));
258                 waypoints.Enqueue(
new Vector3(pos.x, pos.y - 0.5f, 0f));
259             }
260         }
261
262     }
263
264     
private Vector3 getStartPosAccordingToName()
265     {
266         
switch (gameObject.name)
267         {
268             
case "blinky":
269                 
return new Vector3(15f, 20f, 0f);
270
271             
case "pinky":
272                 
return new Vector3(14.5f, 17f, 0f);
273             
274             
case "inky":
275                 
return new Vector3(16.5f, 17f, 0f);
276
277             
case "clyde":
278                 
return new Vector3(12.5f, 17f, 0f);
279         }
280
281         
return new Vector3();
282     }
283
284     
//------------------------------------------------------------------------------------
285     
// Update functions
286     
void animate()
287     {
288         Vector3 dir = waypoint - transform.position;
289         GetComponent<Animator>().SetFloat(
"DirX", dir.x);
290         GetComponent<Animator>().SetFloat(
"DirY", dir.y);
291         GetComponent<Animator>().SetBool(
"Run", false);
292     }
293
294     
void OnTriggerEnter2D(Collider2D other)
295     {
296         
if(other.name == "pacman")
297         {
298             
//Destroy(other.gameObject);
299             
if (state == State.Run)
300             {
301                 Calm();
302                 InitializeGhost(_startPos);
303                 pacman.UpdateScore();
304             }
305                
306             
else
307             {
308                 _gm.LoseLife();
309             }
310
311         }
312     }
313
314     
//-----------------------------------------------------------------------------------
315     
// State functions
316     
void Wait()
317     {
318         
if(Time.time >= timeToEndWait)
319         {
320             state = State.Init;
321             waypoints.Clear();
322             InitializeWaypoints(state);
323         }
324
325         
// get the next waypoint and move towards it
326         MoveToWaypoint(
true);
327     }
328
329     
void Init()
330     {
331         _timeToWhite =
0;
332
333         
// if the Queue is cleared, do some clean up and change the state
334         
if(waypoints.Count == 0)
335         {
336             state = State.Scatter;
337
338             
//get direction according to sprite name
339             
string name = GetComponent<SpriteRenderer>().sprite.name;
340             
if(name[name.Length-1] == '0' || name[name.Length-1] == '1') direction = Vector3.right;
341             
if(name[name.Length-1] == '2' || name[name.Length-1] == '3') direction = Vector3.left;
342             
if(name[name.Length-1] == '4' || name[name.Length-1] == '5') direction = Vector3.up;
343             
if(name[name.Length-1] == '6' || name[name.Length-1] == '7') direction = Vector3.down;
344
345             InitializeWaypoints(state);
346             timeToEndScatter = Time.time + scatterLength;
347
348             
return;
349         }
350
351         
// get the next waypoint and move towards it
352         MoveToWaypoint();
353     }
354
355     
void Scatter()
356     {
357         
if(Time.time >= timeToEndScatter)
358         {
359             waypoints.Clear();
360             state = State.Chase;
361             
return;
362         }
363
364         
// get the next waypoint and move towards it
365         MoveToWaypoint(
true);
366
367     }
368
369     
void ChaseAI()
370     {
371
372         
// if not at waypoint, move towards it
373         
if (Vector3.Distance(transform.position, waypoint) > 0.000000000001)
374         {
375             Vector2 p = Vector2.MoveTowards(transform.position, waypoint, speed);
376             GetComponent<Rigidbody2D>().MovePosition(p);
377         }
378
379         
// if at waypoint, run AI module
380         
else GetComponent<AI>().AILogic();
381
382     }
383
384     
void RunAway()
385     {
386         GetComponent<Animator>().SetBool(
"Run", true);
387
388         
if(Time.time >= _timeToWhite && Time.time >= _timeToToggleWhite) ToggleBlueWhite();
389
390         
// if not at waypoint, move towards it
391         
if (Vector3.Distance(transform.position, waypoint) > 0.000000000001)
392         {
393             Vector2 p = Vector2.MoveTowards(transform.position, waypoint, speed);
394             GetComponent<Rigidbody2D>().MovePosition(p);
395         }
396         
397         
// if at waypoint, run AI run away logic
398         
else GetComponent<AI>().RunLogic();
399
400     }
401
402     
//------------------------------------------------------------------------------
403     
// Utility functions
404     
void MoveToWaypoint(bool loop = false)
405     {
406         waypoint = waypoints.Peek();
// get the waypoint (CHECK NULL?)
407         
if (Vector3.Distance(transform.position, waypoint) > 0.000000000001) // if its not reached
408         {
// move towards it
409             _direction = Vector3.Normalize(waypoint - transform.position);
// dont screw up waypoint by calling public setter
410             Vector2 p = Vector2.MoveTowards(transform.position, waypoint, speed);
411             GetComponent<Rigidbody2D>().MovePosition(p);
412         }
413         
else // if waypoint is reached, remove it from the queue
414         {
415             
if(loop) waypoints.Enqueue(waypoints.Dequeue());
416             
else waypoints.Dequeue();
417         }
418     }
419
420     
public void Frighten()
421     {
422         state = State.Run;
423         _direction *= -
1;
424
425         _timeToWhite = Time.time + _gm.scareLength *
0.66f;
426         _timeToToggleWhite = _timeToWhite;
427         GetComponent<Animator>().SetBool(
"Run_White", false);
428
429     }
430
431     
public void Calm()
432     {
433         
// if the ghost is not running, do nothing
434         
if (state != State.Run) return;
435
436         waypoints.Clear ();
437         state = State.Chase;
438         _timeToToggleWhite =
0;
439         _timeToWhite =
0;
440         GetComponent<Animator>().SetBool(
"Run_White", false);
441         GetComponent<Animator>().SetBool(
"Run", false);
442     }
443
444     
public void ToggleBlueWhite()
445     {
446         isWhite = !isWhite;
447         GetComponent<Animator>().SetBool(
"Run_White", isWhite);
448         _timeToToggleWhite = Time.time + _toggleInterval;
449     }
450
451 }


----------------------------

Navigation variables

private Vector3 waypoint; AI-determined waypoint

private Queue waypoints; waypoints used on Init and Scatter states

direction is set from the AI component

Debug.Log ("waypoint (" + waypoint.position.x + ", " + waypoint.position.y + ") set! _direction: " + _direction.x + ", " + _direction.y);

----------------------------

Ghost mode variables

handles

-----------------------------------------------------------------------------------------

variables end, functions begin

-----------------------------------------------------------------------------------

Start() functions

waypoint = transform.position; to avoid flickering animation

waypoint = transform.position; to avoid flickering animation

--------------------------------------------------

File Format: Init and Scatter coordinates separated by empty line

Init X,Y

Init X,Y

Scatter X,Y

Scatter X,Y

--------------------------------------------------

hardcode waypoints according to name.

-------------------------------------------------

read from the hardcoded waypoints

stop reading if empty line is reached

if (line.Length == 0) break; DOES IT WORK????

skip until empty line is reached, read coordinates afterwards

bool scatterWps = false; Scatter waypoints

scatterWps = true; we reached the scatter waypoints

continue; do not read empty line, go to next line

if in wait state, patrol vertically

inky and clyde start going down and then up

while pinky start going up and then down

------------------------------------------------------------------------------------

Update functions

Destroy(other.gameObject);

-----------------------------------------------------------------------------------

State functions

get the next waypoint and move towards it

if the Queue is cleared, do some clean up and change the state

get direction according to sprite name

get the next waypoint and move towards it

get the next waypoint and move towards it

if not at waypoint, move towards it

if at waypoint, run AI module

if not at waypoint, move towards it

if at waypoint, run AI run away logic

------------------------------------------------------------------------------

Utility functions

waypoint = waypoints.Peek(); get the waypoint (CHECK NULL?)

if (Vector3.Distance(transform.position, waypoint) > 0.000000000001) if its not reached

{ move towards it

_direction = Vector3.Normalize(waypoint - transform.position); dont screw up waypoint by calling public setter

else if waypoint is reached, remove it from the queue

if the ghost is not running, do nothing



Gõ tìm kiếm nhanh...